package com.zy.sso.server.service;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import com.zy.sso.client.dto.BaseUser;
import com.zy.sso.client.dto.login.ClientInfo;
import com.zy.sso.client.dto.login.LoginDTO;
import com.zy.sso.client.dto.login.RequestHeader;
import com.zy.sso.client.dto.logout.LogoutDTO;
import com.zy.sso.client.exception.SsoException;
import com.zy.sso.server.entites.ClientTrack;
import com.zy.sso.server.entites.RequestTrack;
import com.zy.sso.server.entites.User;
import com.zy.sso.server.event.LoginEvent;
import com.zy.sso.server.event.LogoutEvent;
import com.zy.sso.server.event.RegisterEvent;
import com.zy.sso.server.repository.ClientTrackRepository;
import com.zy.sso.server.repository.RequestTrackRepository;
import com.zy.sso.server.repository.UserRepository;

@Service
public class LogService {

    private static final Logger logger =  LoggerFactory.getLogger(LogService.class);

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ClientTrackRepository clientTrackRepository;

    @Autowired
    private RequestTrackRepository requestTrackRepository;

    @Autowired
    private MongoTemplate mongoTemplate;


    /**
     * 用户注册handle
     * **/
    @EventListener
    public void afterRegister(RegisterEvent event) {
        LoginDTO loginDTO = (LoginDTO) event.getSource();
        User user = userRepository.findOneByAccount(loginDTO.getAccount());
        if(user == null) {
            logger.error("账号不存在:{}",loginDTO.getAccount());
            throw new SsoException("账号不存在");
        }
        //销户提示
        if(BaseUser.UserStatus.cancellation == user.getStatus()){
            logger.error("该账号已销户,请换一个账号注册！account:{}",loginDTO.getAccount());
            throw new SsoException("该账号已销户,请换一个账号注册！");
        }
        //save request head
        if(loginDTO.getRequestHeader() != null){
            if(logger.isDebugEnabled()) logger.debug("保存用户请求头信息");
            saveRequestHeader(loginDTO.getRequestHeader(),user.getAccount(), LoginDTO.OptType.regist);
        }
        //save clientInfo
        if(loginDTO.getClientInfo() != null){
            if(logger.isDebugEnabled()) logger.debug("取消其他clientInfo的在线状态");
            clientInfoOffLine(user.getGid());
            //保存clientInfo
            if(logger.isDebugEnabled()) logger.debug("保存用户clientInfo");
            clientInfoOnLine(loginDTO.getClientInfo(),user.getGid(),LoginDTO.OptType.regist, ClientTrack.STATUS_OFFLINE);
        }
    }

    /**
     * 用户登录handle
     * **/
    @EventListener
    public void afterLogin(LoginEvent event) {
        LoginDTO loginDTO = (LoginDTO) event.getSource();
        User user = userRepository.findOneByAccount(loginDTO.getAccount());
        if(user == null) {
            logger.error("账号不存在:{}",loginDTO.getAccount());
            throw new SsoException("账号不存在");
        }
        //销户提示
        if(BaseUser.UserStatus.cancellation == user.getStatus()){
            logger.error("该账号已销户,请换一个账号注册！account:{}",loginDTO.getAccount());
            throw new SsoException("该账号已销户,请换一个账号注册！");
        }
        //save request head
        if(loginDTO.getRequestHeader() != null){
            if(logger.isDebugEnabled()) logger.debug("保存用户请求头信息");
            saveRequestHeader(loginDTO.getRequestHeader(),user.getAccount(), LoginDTO.OptType.login);
        }
        //save clientInfo
        if(loginDTO.getClientInfo() != null){
            if(logger.isDebugEnabled()) logger.debug("取消其他clientInfo的在线状态");
            clientInfoOffLine(user.getGid());
            //保存clientInfo
            if(logger.isDebugEnabled()) logger.debug("保存用户clientInfo");
            clientInfoOnLine(loginDTO.getClientInfo(),user.getGid(),LoginDTO.OptType.regist,ClientTrack.STATUS_ONLINE);
        }
    }

    /**
     * 用户退出登录
     **/
    @EventListener
    public void afterLogin(LogoutEvent event) {
        LogoutDTO logoutDTO = (LogoutDTO) event.getSource();
        User user = userRepository.findOneByAccount(logoutDTO.getAccount());
        if(user == null) {
            logger.error("账号不存在:{}",logoutDTO.getAccount());
            throw new SsoException("账号不存在");
        }
        //销户提示
        if(BaseUser.UserStatus.cancellation == user.getStatus()){
            logger.error("该账号已销户,请换一个账号注册！account:{}",logoutDTO.getAccount());
            throw new SsoException("该账号已销户,请换一个账号注册！");
        }
        //save request head
        if(logoutDTO.getRequestHeader() != null){
            if(logger.isDebugEnabled()) logger.debug("保存用户请求头信息");
            saveRequestHeader(logoutDTO.getRequestHeader(),user.getAccount(), LoginDTO.OptType.logOut);
        }
        //save clientInfo
        if(logoutDTO.getClientInfo() != null){
            if(logger.isDebugEnabled()) logger.debug("取消其他clientInfo的在线状态");
            clientInfoOffLine(user.getGid());
            //保存clientInfo
            if(logger.isDebugEnabled()) logger.debug("保存用户clientInfo");
            clientInfoOnLine(logoutDTO.getClientInfo(),user.getGid(),LoginDTO.OptType.logOut,ClientTrack.STATUS_OFFLINE);
        }
    }

    /**
     * 保存请求信息
     * **/
    private void saveRequestHeader(RequestHeader header, String account, LoginDTO.OptType optType){
        RequestTrack requestTrack = new RequestTrack();
        BeanUtils.copyProperties(header, requestTrack);
        requestTrack.setAccount(account);
        requestTrack.setOptType(optType);
        requestTrackRepository.save(requestTrack);
    }

    /***
     * 创建一条上线clientInfo
     * **/
    private void clientInfoOnLine(ClientInfo clientInfo,String gid,LoginDTO.OptType optType,int status){
        ClientTrack clientTrack = new ClientTrack();
        BeanUtils.copyProperties(clientInfo, clientTrack);
        clientTrack.setStatus(status);
        clientTrack.setGid(gid);
        clientTrack.setOptType(optType);
        clientTrackRepository.save(clientTrack);
    }

    /***
     * 跟新设备下线
     * **/
    private void clientInfoOffLine(String gid){
        Query query = new Query();
        query.addCriteria(Criteria.where("gid").is(gid));
        Update update = new Update();
        update.inc("status", ClientTrack.STATUS_OFFLINE);
        mongoTemplate.updateMulti(query, update, ClientTrack.class);
    }
}
